package net.lab1024.sa.admin.module.workflow.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import net.lab1024.sa.admin.module.workflow.dao.LeaveapplyDao;
import net.lab1024.sa.admin.module.workflow.domain.entity.LeaveApply;
import net.lab1024.sa.admin.module.workflow.domain.leave.bo.LeaveApplyBo;
import net.lab1024.sa.admin.module.workflow.domain.vo.LeaveApplyVo;
import net.lab1024.sa.admin.util.ProcessUtils;
import net.lab1024.sa.base.common.domain.WorkFlowBusinessBo;
import net.lab1024.sa.base.common.service.WorkFlowCommonService;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.ExclusiveGateway;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext;
import org.flowable.common.engine.impl.javax.el.ELContext;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 请假Service业务层处理
 *
 * @author ruoyi
 * @date 2024-12-10
 */

@Service
public class LeaveApplyService implements WorkFlowCommonService<LeaveApplyBo> {

    @Resource
    private LeaveapplyDao baseMapper;

    @Resource
    IdentityService identityService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private LeaveapplyDao leaveapplyMapper;

    @Resource
    private WfProcessService processService;


    @Resource
    private RepositoryService repositoryService;

    /**
     * 查询请假
     */

    public LeaveApply queryById(Long id) {
        return baseMapper.selectById(id);
    }

    /**
     * 查询请假列表
     */
//    public PageResult<LeaveapplyVo> queryPageList(LeaveapplyBo bo) {
//        Page<?> page = SmartPageUtil.convert2PageQuery(bo);
//        List<LeaveapplyVo> list = baseMapper.queryPageList(page, bo);
//        PageResult<LeaveapplyVo> pageResult = SmartPageUtil.convert2PageResult(page, list);
//        return pageResult;
//    }

    /**
     * 查询请假列表
     */
    public List<LeaveApplyVo> queryList(LeaveApplyBo bo) {
        List<LeaveApplyVo> list = baseMapper.queryList(bo);
        return list;
    }


    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(LeaveApply entity) {
        //TODO 做一些数据校验,如唯一约束
    }


    public LeaveApply queryByProcInsId(String procInsId) {
        return baseMapper.selectOne(new LambdaQueryWrapper<LeaveApply>().eq(LeaveApply::getProcessInstanceId, procInsId));
    }


    public String previewLeave2(String processKey, LeaveApplyBo bo) {
        //获取流程定义
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processKey).latestVersion().singleResult();
        //获取所有的节点信息
        List<Task> list = taskService.createTaskQuery().processDefinitionId(processDefinition.getId()).list();

        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();

        for (FlowElement flowElement : flowElements) {
            //节点是否有分支
            if (flowElement instanceof ExclusiveGateway) {
                ExclusiveGateway exclusiveGateway = (ExclusiveGateway) flowElement;
                //获取分支条件

                List<SequenceFlow> outgoingFlows = exclusiveGateway.getOutgoingFlows();
                outgoingFlows.forEach(sequenceFlow -> {
                    //判断条件是否满足
                    if (sequenceFlow.getConditionExpression() != null) {
                        String conditionExpression = sequenceFlow.getConditionExpression();
                        //解析表达式
                        ELContext simpleContext = new SimpleContext();
                    }

                });

            }
        }


        InputStream inputStream = repositoryService.getProcessModel(processDefinition.getId());
        String bpmnXmlStr = StrUtil.utf8Str(IoUtil.readBytes(inputStream, false));


        return bpmnXmlStr;


    }


    @Override
    public Object save(LeaveApplyBo bo) {
        try {
            // 转换为实体并设置基础信息
            LeaveApply leaveapply = BeanUtil.toBean(bo, LeaveApply.class);
            leaveapply.setId(IdUtil.getSnowflakeNextId());
            // 保存数据
            leaveapplyMapper.insert(leaveapply);

            return leaveapply;
        } catch (Exception e) {
            throw new RuntimeException("保存请假申请失败: " + e.getMessage(), e);
        }
    }

    @Override
    public LeaveApply update(LeaveApplyBo bo) {
        LeaveApply leaveapply = BeanUtil.toBean(bo, LeaveApply.class);
        leaveapplyMapper.updateById(leaveapply);
        return leaveapply;
    }

    @Override
    public LeaveApply commit(WorkFlowBusinessBo businessBo, LeaveApplyBo bo) {
        LeaveApply leaveapply = BeanUtil.toBean(bo, LeaveApply.class);
        leaveapply.setId(IdUtil.getSnowflakeNextId());
        leaveapplyMapper.insert(leaveapply);

        Map<String, Object> variables = businessBo.getVariables();
        variables.put("days", leaveapply.getDays());
        variables.put("depts", CollectionUtils.isEmpty(bo.getDepts()) ? new ArrayList<>() : bo.getDepts());
        variables.put("allSubProcessSuccess", false);

        ProcessUtils.setBusinessVariables(leaveapply.getId(), this.getClass(), variables);
        ProcessInstance processInstance = processService.startProcessByDefId(businessBo.getDefinitionId(), variables);
        leaveapply.setProcessInstanceId(processInstance.getProcessInstanceId());
        leaveapplyMapper.updateById(leaveapply);
        return leaveapply;
    }

    @Override
    public LeaveApplyVo getByInsId(String id) {
        LeaveApply leaveApply = leaveapplyMapper.selectOne(new LambdaQueryWrapper<LeaveApply>().eq(LeaveApply::getProcessInstanceId, id));

        return BeanUtil.copyProperties(leaveApply, LeaveApplyVo.class);

    }

    @Override
    public LeaveApplyVo get(Long id) {
        LeaveApply leaveapply = leaveapplyMapper.selectById(id);
        return BeanUtil.copyProperties(leaveapply, LeaveApplyVo.class);
    }

    @Override
    public Boolean delete(Long id) {
        leaveapplyMapper.deleteById(id);
        return true;
    }
}
